package com.code.test.second.hash;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 第454题.四数相加II
 * 力扣题目链接
 * <p>
 * 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ，使得 A[i] + B[j] + C[k] + D[l] = 0。
 * <p>
 * 为了使问题简单化，所有的 A, B, C, D 具有相同的长度 N，且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间，最终结果不会超过 2^31 - 1 。
 * <p>
 * 例如:
 * <p>
 * 输入:
 * <p>
 * A = [ 1, 2]
 * B = [-2,-1]
 * C = [-1, 2]
 * D = [ 0, 2]
 * 输出:
 * <p>
 * 2
 * <p>
 * 解释:
 * <p>
 * 两个元组如下:
 * <p>
 * (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
 * (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
 */
public class SCode454 {

    public static void main(String[] args) {
        int[] A = {1, 2};
        int[] B = {-2, -1};
        int[] C = {-1, 2};
        int[] D = {0, 2};
        int count = fourSumCount(A, B, C, D);
        System.out.println(count);
    }

    /**
     * 注意：
     * 本题是4个数组
     */
    public static int fourSumCount(int[] num1, int[] num2, int[] num3, int[] num4) {
        /**
         * 遍历数组1和2，统计2个数组元素的和、次数
         * key:a+b
         * value：count
         *
         * a+b+c+d=0
         * a+c = b+d
         * a+b = c+d
         */
        Map<Integer, Integer> map1 = new HashMap<>();

        for (int i : num1) {
            for (int j : num2) {
                int sum = i + j;
                map1.put(sum, map1.getOrDefault(sum, 0) + 1);
            }
        }

        int count = 0;
        for (int i : num3) {
            for (int j : num4) {
                //四个数组，任意2个相加，跟另外任意2个是相反数，才会等于0
                int curSum = -(i + j);
                //然后判断这个取反的数在map是否存在
                if (map1.containsKey(curSum)) {
                    //上面map存的是数量
                    count += map1.get(curSum);

                }
            }
        }
        return count;

    }
}
